﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Hockey.UILayer.Controls
{
    /// <summary>
    /// Class drawing arrow
    /// override Brush and TransformProperty
    /// </summary>
    internal class Arrow: ContentControl
    {
        /// <summary>
        /// Drawing constants
        /// </summary>
        private const double _headerRatioY = 1d / 4d;
        private const double _headerRatioX = 1d / 3d;

        // overrides DependencyProperties
        public static readonly DependencyProperty FillProperty;
        public static readonly DependencyProperty StrokeProperty;
        public static readonly DependencyProperty StrokeThicknessProperty;

        /// <summary>
        /// Polygon object representing arrow
        /// </summary>
        private Polygon _arrowPolygon;

        static Arrow()
        {            
            FrameworkPropertyMetadata metadata1 = new FrameworkPropertyMetadata();
            metadata1.Inherits = true;
            
            FrameworkPropertyMetadata metadata2 = new FrameworkPropertyMetadata();
            metadata2.Inherits = true;

            FrameworkPropertyMetadata metadata3 = new FrameworkPropertyMetadata();
            metadata3.Inherits = true;

            FillProperty = Polygon.FillProperty.AddOwner(typeof(Arrow));
            FillProperty.OverrideMetadata(typeof(Arrow), metadata1);

            StrokeProperty = Shape.StrokeProperty.AddOwner(typeof(Arrow));
            StrokeProperty.OverrideMetadata(typeof(Arrow), metadata2);

            StrokeThicknessProperty = Shape.StrokeThicknessProperty.AddOwner(typeof(Arrow));
            StrokeThicknessProperty.OverrideMetadata(typeof(Arrow), metadata3);
        }

        /// <summary>
        /// Constructor
        /// </summary>
        public Arrow()
        {
            _arrowPolygon = new Polygon();
            this.SizeChanged += Arrow_SizeChanged;

            BuildArrowPolygon();
            this.Content = _arrowPolygon;
        }

        #region CLR Wrappers for DependecyProperties

        public Brush Fill
        {
            get
            {
                return (Brush)GetValue(FillProperty);
            }
            set
            {
                SetValue(FillProperty, value);
            }
        }

        public Brush Stroke
        {
            get
            {
                return (Brush)GetValue(StrokeProperty);
            }
            set
            {
                SetValue(StrokeProperty, value);
            }
        }

        public double StrokeThickness
        {
            get
            {
                return (double)GetValue(StrokeThicknessProperty);
            }
            set
            {
                SetValue(StrokeThicknessProperty, value);
            }
        }

        #endregion

        /// <summary>
        /// Handler for resizing arrow polygon when size has changed
        /// </summary>
        void Arrow_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            BuildArrowPolygon();
            
            // refresh render transform property
            Transform objTransform = this.RenderTransform;
            this.RenderTransform = null;
            this.RenderTransform = objTransform;
        }

        /// <summary>
        /// Make rotating around the center
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.Property.Name == "RenderTransform" && e.NewValue != null)
            {
                RotateTransform trans = e.NewValue as RotateTransform;
                if (trans == null)
                    return;
                trans.CenterX = RenderSize.Width / 2;
                trans.CenterY = RenderSize.Height / 2;
            }

            // Polygon possibly does not have inheriting in its properties, we have to override it like this
            if (_arrowPolygon != null)
            {
                if (e.Property.Name == "Fill")
                {
                    _arrowPolygon.SetValue(Shape.FillProperty, e.NewValue);
                }
                else if (e.Property.Name == "Stroke")
                {
                    _arrowPolygon.SetValue(Shape.StrokeProperty, e.NewValue);
                }
                else if (e.Property.Name == "StrokeThickness")
                {
                    _arrowPolygon.SetValue(Shape.StrokeThicknessProperty, e.NewValue);
                }
            }

            base.OnPropertyChanged(e);
        }

        /// <summary>
        /// Builds the arrow polygon
        /// </summary>
        private void BuildArrowPolygon()
        {
            // clear points
            _arrowPolygon.Points.Clear();

            // add top point
            double middleX = RenderSize.Width / 2;
            _arrowPolygon.Points.Add(new Point(middleX, 0));

            // add right header point
            double headerY = RenderSize.Height * _headerRatioY;
            _arrowPolygon.Points.Add(new Point(middleX + headerY, headerY));

            // add bottom header point on the right
            double bottomHeaderSize = (headerY * 2) * _headerRatioX;
            double rightX = middleX + headerY - bottomHeaderSize;
            _arrowPolygon.Points.Add(new Point(rightX, headerY));

            // add points for arrow column
            _arrowPolygon.Points.Add(new Point(rightX, RenderSize.Height));
            double leftX = rightX - bottomHeaderSize;
            _arrowPolygon.Points.Add(new Point(leftX, RenderSize.Height));
            _arrowPolygon.Points.Add(new Point(leftX, headerY));

            // add final left header point
            _arrowPolygon.Points.Add(new Point(leftX - bottomHeaderSize, headerY));         
        }
    }
}
